# -*- coding: utf-8 -*-
"""
车辆标定按钮控制模块
负责管理标定按钮的状态、样式和交互逻辑
"""

from PySide2.QtWidgets import QPushButton, QHBoxLayout, QWidget, QSizePolicy
from PySide2.QtCore import Qt, Signal, Slot, QPropertyAnimation, QEasingCurve, QObject
from PySide2.QtGui import QFont, QIcon, QPixmap
from typing import Dict, List, Optional, Tuple
from gglobal import logger, config
from ..handlercore.language_manager import LanguageManager
from ..handlercore.theme_manager import ThemeManager
from ..handlercore.signal_manager import create_signal_manager


class CalibrationButtonStyles:
    """
    标定按钮样式定义类
    使用CSS类名而非内联样式，提高可维护性
    """
    
    # 按钮状态对应的CSS类名
    STATE_CLASS_MAP = {
        "enabled": "calibration-button-enabled",
        "disabled": "calibration-button-disabled", 
        "running": "calibration-button-running",
        "success": "calibration-button-success",
        "error": "calibration-button-error"
    }
    
    @classmethod
    def get_style_class(cls, state: str) -> str:
        """
        获取指定状态的CSS类名
        
        Args:
            state: 按钮状态 (enabled, disabled, running, success, error)
            
        Returns:
            str: CSS类名
        """
        base_class = "calibration-button"
        state_class = cls.STATE_CLASS_MAP.get(state, cls.STATE_CLASS_MAP["disabled"])
        return f"{base_class} {state_class}"
    
    @classmethod
    def get_style(cls, state: str, theme: str = "light") -> str:
        """
        获取指定状态和主题的样式
        
        Args:
            state: 按钮状态 (enabled, disabled, running, success, error)
            theme: 主题 (light, dark)
            
        Returns:
            str: CSS样式字符串
        """
        styles = cls.DARK_STYLES if theme == "dark" else cls.LIGHT_STYLES
        return styles.get(state, styles.get("disabled", ""))


class CalibrationButton(QPushButton):
    """
    自定义标定按钮类
    支持状态管理、动画效果和样式控制
    """
    
    # 按钮状态枚举
    STATE_ENABLED = "enabled"
    STATE_DISABLED = "disabled"
    STATE_RUNNING = "running"
    STATE_SUCCESS = "success"
    STATE_ERROR = "error"
    
    # 信号定义
    calibration_requested = Signal(str, str)  # 标定请求信号 (calibration_type, button_type)
    
    def __init__(self, calibration_type: str, button_type: str = "single", parent=None):
        """
        初始化标定按钮
        
        Args:
            calibration_type: 标定类型
            button_type: 按钮类型 ("single", "left", "right")
            parent: 父控件
        """
        super(CalibrationButton, self).__init__(parent)
        
        self.calibration_type = calibration_type
        self.button_type = button_type
        # 初始化状态（设置为None以确保首次set_state能够正确应用）
        self.current_state = None
        
        # 获取管理器
        self.language_manager = LanguageManager()
        self.theme_manager = ThemeManager()
        self._signal_manager = create_signal_manager("CalibrationButton", self)
        
        # 设置按钮自适应属性
        self._setup_adaptive_sizing()
        
        # 设置按钮文本
        self._update_button_text()
        
        self._signal_manager.register_connection("lang_changed", self.language_manager.language_changed, self._on_language_changed)
        self._signal_manager.register_connection("theme_changed", self.theme_manager.theme_changed, self._on_theme_changed)
        self._signal_manager.connect_all()
        
        # 设置初始状态和样式
        self.set_state(self.STATE_DISABLED)
    
    def _setup_adaptive_sizing(self):
        """设置按钮自适应尺寸"""
        # 获取系统DPI缩放比例
        from PySide2.QtWidgets import QApplication
        screen = QApplication.primaryScreen()
        dpi_ratio = screen.logicalDotsPerInch() / 96.0  # 96 DPI为标准
        
        # 基础尺寸（考虑DPI缩放）
        base_min_width = int(100 * dpi_ratio)
        base_max_width = int(180 * dpi_ratio)
        base_height = int(32 * dpi_ratio)
        
        # 设置最小和最大尺寸
        self.setMinimumSize(base_min_width, base_height)
        self.setMaximumSize(base_max_width, base_height)
        
        # 设置尺寸策略：宽度可扩展，高度固定
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        
        # 设置内容边距（考虑DPI缩放）
        padding = int(8 * dpi_ratio)
        self.setContentsMargins(padding, 0, padding, 0)
    
    def _update_button_text(self):
        """更新按钮文本"""
        if self.button_type == "single":
            # 单按钮统一使用“开始标定”
            text_key = "calibration_button_start"
            default_text = "开始标定"
        elif self.button_type == "left":
            # 左按钮：针对上下激光联合标定显示“左下激光标定”，否则沿用叉臂相机
            if self.calibration_type == "calibration_menu_laser_joint":
                text_key = "calibration_button_left_bottom_laser"
                default_text = "左下激光标定"
            else:
                text_key = "calibration_button_left_fork"
                default_text = "左叉臂相机标定"
        elif self.button_type == "right":
            # 右按钮：针对上下激光联合标定显示“右下激光标定”，否则沿用叉臂相机
            if self.calibration_type == "calibration_menu_laser_joint":
                text_key = "calibration_button_right_bottom_laser"
                default_text = "右下激光标定"
            else:
                text_key = "calibration_button_right_fork"
                default_text = "右叉臂相机标定"
        else:
            text_key = "calibration_button_start"
            default_text = "开始标定"
        
        button_text = self.language_manager.get_text(text_key, default_text)
        self.setText(button_text)
    
    def _on_language_changed(self, language_data):
        """语言切换时更新按钮文本"""
        self._update_button_text()
    
    def _on_theme_changed(self, theme_name: str):
        """主题切换时更新按钮样式"""
        self._apply_current_style()
    
    @Slot()
    def _on_button_clicked(self):
        """按钮点击事件处理"""
        if self.current_state == self.STATE_ENABLED:
            logger.info(f"标定按钮点击: {self.calibration_type} - {self.button_type}")
            try:
                mgr = None
                p = self.parent()
                while p is not None and mgr is None:
                    if hasattr(p, "button_manager"):
                        mgr = getattr(p, "button_manager", None)
                        break
                    p = p.parent()
                if mgr is not None:
                    mgr.calibration_requested.emit(self.calibration_type, self.button_type)
                else:
                    self.calibration_requested.emit(self.calibration_type, self.button_type)
            except RuntimeError as e:
                logger.warning(f"按钮点击处理异常: {e}")
    
    def _apply_current_style(self):
        """应用当前状态的样式"""
        try:
            # 获取CSS类名
            style_class = CalibrationButtonStyles.get_style_class(self.current_state)
            
            # 设置CSS类名
            self.setProperty("class", style_class)
            
            # 强制刷新样式
            self.style().unpolish(self)
            self.style().polish(self)
            self.update()
            
        except Exception as e:
            logger.error(f"样式应用失败: {self.calibration_type} - {self.button_type} - {e}")
    
    def set_state(self, state: str):
        """
        设置按钮状态
        
        Args:
            state: 按钮状态
        """
        if state == self.current_state:
            return
        
        old_state = self.current_state
        self.current_state = state
        
        # 根据状态设置按钮属性
        if state == self.STATE_ENABLED:
            self.setEnabled(True)
        elif state == self.STATE_DISABLED:
            self.setEnabled(False)
        elif state == self.STATE_RUNNING:
            self.setEnabled(False)
            self._start_running_animation()
        elif state == self.STATE_SUCCESS:
            self.setEnabled(True)
        elif state == self.STATE_ERROR:
            self.setEnabled(True)
        
        # 立即应用新状态的样式
        self._apply_current_style()
        
        # 确保父控件也更新样式
        if self.parent():
            self.parent().update()
    
    def _start_running_animation(self):
        """启动运行状态动画"""
        # 这里可以添加按钮运行时的动画效果
        # 例如文本闪烁、颜色变化等
        pass
    
    def get_state(self) -> str:
        """获取当前按钮状态"""
        return self.current_state


class CalibrationButtonManager(QObject):
    """
    标定按钮管理器
    负责管理所有标定按钮的创建、状态控制和布局
    """
    
    # 按钮配置：定义哪些标定项需要什么类型的按钮
    BUTTON_CONFIGS = {
        "calibration_menu_laser_yaw": {"type": "single"},
        # 默认类型为single
        "calibration_menu_laser_joint": {"type": "single"},
        "calibration_menu_mid360": {"type": "single"},
        "calibration_menu_fork_camera": {"type": "dual"},
        "calibration_menu_fork_camera_sub1": {"type": "dual"},
        "calibration_menu_recognition_camera_sub1": {"type": "single"},
        "calibration_menu_recognition_camera_sub2": {"type": "dual"}
    }
    
    # 信号定义
    calibration_requested = Signal(str, str)  # 标定请求信号
    
    def __init__(self, parent=None):
        """初始化按钮管理器"""
        super(CalibrationButtonManager, self).__init__(parent)
        self.parent = parent
        self.buttons = {}  # 存储所有按钮 {calibration_type: {button_type: button}}
        self.button_widgets = {}  # 存储按钮容器控件 {calibration_type: widget}
        self.current_calibration = None
        # 语言管理器用于获取当前语言的检测项显示文本
        self.language_manager = LanguageManager()
        
        logger.info("标定按钮管理器初始化完成")
    
    def create_button_widget(self, calibration_type: str) -> Optional[QWidget]:
        """
        为指定标定类型创建按钮控件
        
        Args:
            calibration_type: 标定类型
            
        Returns:
            QWidget: 按钮容器控件，如果配置不存在则返回None
        """
        if calibration_type not in self.BUTTON_CONFIGS:
            logger.warning(f"未找到标定类型 {calibration_type} 的按钮配置")
            return None
        
        config_item = self.BUTTON_CONFIGS[calibration_type]
        button_type = config_item["type"]

        
        
        # 创建容器控件
        container = QWidget(self.parent)
        layout = QHBoxLayout(container)
        
        # 获取系统DPI缩放比例
        from PySide2.QtWidgets import QApplication
        screen = QApplication.primaryScreen()
        dpi_ratio = screen.logicalDotsPerInch() / 96.0
        
        # 设置布局边距和间距（考虑DPI缩放）
        margin = int(8 * dpi_ratio)
        spacing = int(10 * dpi_ratio)
        
        layout.setContentsMargins(margin, 0, margin, 0)
        layout.setSpacing(spacing)
        
        # 初始化按钮字典
        if calibration_type not in self.buttons:
            self.buttons[calibration_type] = {}
        
        # 添加弹性空间，将按钮推到右侧
        layout.addStretch()
        
        if button_type == "single":
            button = CalibrationButton(calibration_type, "single", container)
            ct = calibration_type
            bt = "single"
            from ..handlercore.signal_manager import create_signal_manager
            if not hasattr(self, "_signal_manager"):
                self._signal_manager = create_signal_manager("CalibrationButtonManager", self)
            self._signal_manager.register_connection(f"clicked_{id(button)}", button.clicked, lambda ct=ct, bt=bt: self.calibration_requested.emit(ct, bt), Qt.QueuedConnection)
            self._signal_manager.connect_signal(f"clicked_{id(button)}")
            layout.addWidget(button)
            self.buttons[calibration_type]["single"] = button
            
        elif button_type == "dual":
            left_button = CalibrationButton(calibration_type, "left", container)
            right_button = CalibrationButton(calibration_type, "right", container)
            ct = calibration_type
            from ..handlercore.signal_manager import create_signal_manager
            if not hasattr(self, "_signal_manager"):
                self._signal_manager = create_signal_manager("CalibrationButtonManager", self)
            self._signal_manager.register_connection(f"clicked_{id(left_button)}", left_button.clicked, lambda ct=ct: self.calibration_requested.emit(ct, "left"), Qt.QueuedConnection)
            self._signal_manager.register_connection(f"clicked_{id(right_button)}", right_button.clicked, lambda ct=ct: self.calibration_requested.emit(ct, "right"), Qt.QueuedConnection)
            self._signal_manager.connect_signal(f"clicked_{id(left_button)}")
            self._signal_manager.connect_signal(f"clicked_{id(right_button)}")
            layout.addWidget(left_button)
            layout.addWidget(right_button)
            self.buttons[calibration_type]["left"] = left_button
            self.buttons[calibration_type]["right"] = right_button
        
        # 保存容器控件
        self.button_widgets[calibration_type] = container
        
        return container
    
    def get_button_widget(self, calibration_type: str) -> Optional[QWidget]:
        """
        获取指定标定类型的按钮控件
        
        Args:
            calibration_type: 标定类型
            
        Returns:
            QWidget: 按钮容器控件
        """
        return self.button_widgets.get(calibration_type)
    
    def update_button_states(self, calibration_type: str, data_status: Dict[str, bool], 
                           global_disable: bool = False):
        """
        更新指定标定类型的按钮状态 - 增强调试日志
        
        Args:
            calibration_type: 标定类型
            data_status: 数据状态字典
            global_disable: 是否全局禁用
        """
        logger.info(f"[CalibrationButtonManager] 开始更新按钮状态: {calibration_type}")
        logger.info(f"[CalibrationButtonManager] 数据状态: {data_status}")
        logger.info(f"[CalibrationButtonManager] 全局禁用: {global_disable}")
        
        if calibration_type not in self.buttons:
            logger.warning(f"[CalibrationButtonManager] 未找到标定类型 {calibration_type} 的按钮")
            return
        
        buttons = self.buttons[calibration_type]
        logger.info(f"[CalibrationButtonManager] 找到按钮: {list(buttons.keys())}")
        
        if global_disable:
            # 全局禁用：禁用所有按钮
            logger.info("[CalibrationButtonManager] 全局禁用模式，禁用所有按钮")
            for button_type, button in buttons.items():
                logger.info(f"[CalibrationButtonManager] 禁用按钮: {button_type}")
                button.set_state(CalibrationButton.STATE_DISABLED)
            return
        
        # 根据按钮类型和数据状态更新
        config_item = self.BUTTON_CONFIGS.get(calibration_type, {})
        button_type = config_item.get("type", "single")
        logger.info(f"[CalibrationButtonManager] 按钮配置类型: {button_type}")
        
        if button_type == "single":
            # 单按钮：检查所有必需数据是否有效
            all_valid = all(data_status.values())
            state = CalibrationButton.STATE_ENABLED if all_valid else CalibrationButton.STATE_DISABLED
            logger.info(f"[CalibrationButtonManager] 单按钮模式 - 所有数据有效: {all_valid}, 设置状态: {state}")
            if "single" in buttons:
                buttons["single"].set_state(state)
                logger.info(f"[CalibrationButtonManager] 单按钮状态已设置为: {state}")
            else:
                logger.warning("[CalibrationButtonManager] 未找到单按钮，可能动态为双按钮模式")
            
        elif button_type == "dual":
            if calibration_type == "calibration_menu_laser_joint":
                # 上下激光联合标定双按钮模式：
                # 按钮可用性仅依赖除“下激光数据”外的其他数据项是否有效。
                other_data_valid = True
                # 根据当前语言获取“下激光数据”的显示文本键
                bottom_laser_key = self.language_manager.get_text(
                    "data_detection_bottom_laser", "下激光数据"
                )
                for key, value in data_status.items():
                    if key != bottom_laser_key:
                        if not value:
                            other_data_valid = False
                            logger.info(f"[CalibrationButtonManager] 其他数据无效: {key} = {value}")
                            break
                logger.info(f"[CalibrationButtonManager] 激光联合双按钮 - 其他数据有效性: {other_data_valid}")

                left_state = CalibrationButton.STATE_ENABLED if other_data_valid else CalibrationButton.STATE_DISABLED
                right_state = CalibrationButton.STATE_ENABLED if other_data_valid else CalibrationButton.STATE_DISABLED
                if "left" in buttons:
                    buttons["left"].set_state(left_state)
                if "right" in buttons:
                    buttons["right"].set_state(right_state)
                logger.info(f"[CalibrationButtonManager] 左按钮状态: {left_state}, 右按钮状态: {right_state}")
            else:
                # 双按钮：分别检查左右叉臂相机状态
                # 使用语言键获取显示名称，避免中文硬编码
                left_camera_key = self.language_manager.get_text("data_detection_left_fork_camera", "左叉臂相机")
                right_camera_key = self.language_manager.get_text("data_detection_right_fork_camera", "右叉臂相机")
                left_camera_valid = data_status.get(left_camera_key, False)
                right_camera_valid = data_status.get(right_camera_key, False)
                logger.info(f"[CalibrationButtonManager] 双按钮模式 - 左叉臂相机({left_camera_key}): {left_camera_valid}, 右叉臂相机({right_camera_key}): {right_camera_valid}")
                
                # 检查其他必需数据（除了叉臂相机）
                other_data_valid = True
                for key, value in data_status.items():
                    if key not in [left_camera_key, right_camera_key]:
                        if not value:
                            other_data_valid = False
                            logger.info(f"[CalibrationButtonManager] 其他数据无效: {key} = {value}")
                            break
                logger.info(f"[CalibrationButtonManager] 其他数据有效性: {other_data_valid}")
                
                # 左按钮状态
                left_state = (CalibrationButton.STATE_ENABLED 
                             if (left_camera_valid and other_data_valid) 
                             else CalibrationButton.STATE_DISABLED)
                if "left" in buttons:
                    buttons["left"].set_state(left_state)
                logger.info(f"[CalibrationButtonManager] 左按钮状态已设置为: {left_state}")
                
                # 右按钮状态
                right_state = (CalibrationButton.STATE_ENABLED 
                              if (right_camera_valid and other_data_valid) 
                              else CalibrationButton.STATE_DISABLED)
                if "right" in buttons:
                    buttons["right"].set_state(right_state)
                logger.info(f"[CalibrationButtonManager] 右按钮状态已设置为: {right_state}")
        
        logger.info(f"[CalibrationButtonManager] 按钮状态更新完成: {calibration_type}")
    
    def set_calibration_running(self, calibration_type: str, button_type: str = "single"):
        """
        设置指定按钮为运行状态
        
        Args:
            calibration_type: 标定类型
            button_type: 按钮类型
        """
        if calibration_type in self.buttons and button_type in self.buttons[calibration_type]:
            self.buttons[calibration_type][button_type].set_state(CalibrationButton.STATE_RUNNING)
            logger.info(f"设置按钮运行状态: {calibration_type} - {button_type}")
    
    def set_calibration_finished(self, calibration_type: str, button_type: str = "single", 
                                success: bool = True):
        """
        设置指定按钮为完成状态
        
        Args:
            calibration_type: 标定类型
            button_type: 按钮类型
            success: 是否成功
        """
        if calibration_type in self.buttons and button_type in self.buttons[calibration_type]:
            state = CalibrationButton.STATE_SUCCESS if success else CalibrationButton.STATE_ERROR
            self.buttons[calibration_type][button_type].set_state(state)
            logger.info(f"设置按钮完成状态: {calibration_type} - {button_type} - {'成功' if success else '失败'}")
    
    def reset_all_buttons(self):
        """重置所有按钮状态"""
        for calibration_type, buttons in self.buttons.items():
            for button in buttons.values():
                button.set_state(CalibrationButton.STATE_DISABLED)
        logger.info("重置所有按钮状态")
    
    def get_button_states(self) -> Dict[str, Dict[str, str]]:
        """
        获取所有按钮的状态
        
        Returns:
            Dict[str, Dict[str, str]]: 按钮状态字典
        """
        states = {}
        for calibration_type, buttons in self.buttons.items():
            states[calibration_type] = {}
            for button_type, button in buttons.items():
                states[calibration_type][button_type] = button.get_state()
        return states
    
    def cleanup(self):
        """清理资源"""
        if hasattr(self, "_signal_manager"):
            try:
                self._signal_manager.disconnect_all()
            except Exception:
                pass
        for container in self.button_widgets.values():
            if container:
                container.deleteLater()
        
        self.buttons.clear()
        self.button_widgets.clear()
        logger.info("标定按钮管理器资源清理完成")